package com.lotso.web.module.batch.entity;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.toolkit.IdWorker;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.lotso.web.common.utils.StringUtil;
import com.lotso.web.module.base.AbstractDataEntity;
import lombok.Getter;
import lombok.Setter;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * ClassName: BatchSchedule
 * Description: 批处理任务计划
 * Date: 2018/9/6 14:27 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 * todo 增加 BatchSchedule 的数据VO层
 */
@Setter
@Getter
@TableName("t_batch_schedule")
public class BatchSchedule extends AbstractDataEntity {

    public static final String SCHEDULE_KEY = "scheduleJob";
    public static final String DEFAULT_CODE_PREFIX = "BS";
    private static final int RUN_ONE_TIME = 1;

    @TableField(exist = false)
    private static final Joiner JOINER = Joiner.on("#");

    /**
     * 计划编码
     */
    private String code;

    /**
     * 计划名称
     */
    private String name;

    /**
     * 计划状态: 整个生命周期状态
     */
    private Integer status;
    @TableField(exist = false)
    private String statusStr;

    /**
     * 执行表达式类型
     */
    private Integer cronType;
    @TableField(exist = false)
    private String cronTypeStr;

    /**
     * 执行表达式
     */
    private String cronExpression;
    @TableField(exist = false)
    private String cronSecond;
    @TableField(exist = false)
    private String cronMinute;
    @TableField(exist = false)
    private String cronHour;
    @TableField(exist = false)
    private String cronDay;
    @TableField(exist = false)
    private String cronMonth;
    @TableField(exist = false)
    private String cronDayOfWeek;

    /**
     * 描述
     */
    private String description;


    /**
     * 处理业务类
     */
    private String interfaceName;

    /**
     * 任务编码（任务组的概念）
     */
    private String taskCode;
    @TableField(exist = false)
    private String taskName;


    /**
     * 指定服务器
     */
    private String serverIp;

    /**
     * 开始时间（最近）
     */
    private Date startDate;

    /**
     * 结束时间（最近）
     */
    private Date endDate;

    /**
     * 前置计划列表
     */
    @TableField(exist = false)
    private List<BatchSchedule> dependencies;

    /**
     * 参数列表
     */
    @TableField(exist = false)
    private List<BatchScheduleParam> params;
    @TableField(exist = false)
    private String paramsJson;

    public BatchSchedule() {
    }

    public BatchSchedule(String id) {
        super(id);
    }

    /**
     * 处理计划Cron表达式
     * 置空的情况：依赖其他计划、执行一次、数据不完整
     *
     * @return
     */
    public BatchSchedule buildCronExpression() {
        boolean flag = (Objects.nonNull(dependencies) && !dependencies.isEmpty())
                || this.cronType == RUN_ONE_TIME
                || StringUtil.hasNullOrEmpty(cronSecond, cronMinute, cronHour, cronDay, cronMonth, cronDayOfWeek);

        if (flag) {
            this.cronExpression = "";
        } else {
            this.cronExpression = JOINER.join(cronSecond, cronMinute, cronHour, cronDay, cronMonth, cronDayOfWeek).trim();
        }
        return this;
    }

    /**
     * 初始化Code
     *
     * @return
     */
    public BatchSchedule initCode() {
        this.code = Strings.isNullOrEmpty(this.code) ? (DEFAULT_CODE_PREFIX + IdWorker.getIdStr()) : this.code;
        return this;
    }

    /**
     * 创建参数
     *
     * @return
     */
    public BatchSchedule buildParams() {
        if (!Strings.isNullOrEmpty(paramsJson)) {
            this.params = JSON.parseArray(paramsJson, BatchScheduleParam.class);
        }
        return this;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("code", code)
                .add("name", name)
                .add("taskCode", taskCode)
                .toString();
    }

    public String toJSON() {
        return JSON.toJSONString(this);
    }
}
